//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#include <buola/buola.h>
#include <buola/io.h>
#include <fstream>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <stdio.h>

#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"

int main()
{
    int lCount=10000030;
    uint64_t lInteger=12357;
    
    using namespace buola;
    start_timer();
    {
        std::ofstream lStream("tonto1.txt");
        for(int i=0;i<lCount;i++)
            lStream << "abcdef\n";
    }
    end_timer("ofstream string    ");
    
    start_timer();
    {
        io::CTextWriter lWriter(io::file("tonto2.txt"),io::EMode::TRUNCATE);
        for(int i=0;i<lCount;i++)
            lWriter << "abcdef\n";
    }
    end_timer("CTextWriter string ");

    start_timer();
    {
        boost::iostreams::stream<boost::iostreams::file_sink> lStream("tonto3.txt");
        for(int i=0;i<lCount;i++)
            lStream << "abcdef\n";
    }
    end_timer("boost string       ");

    start_timer();
    {
        FILE *file=fopen("tonto7.txt","w");
        for(int i=0;i<lCount;i++)
            fprintf(file,"%s","abcdef\n");
        fclose(file);
    }
    end_timer("fprintf string     ");

    start_timer();
    {
        FILE *file=fopen("tonto9.txt","w");
        for(int i=0;i<lCount;i++)
            fputs("abcdef\n",file);
        fclose(file);
    }
    end_timer("fputs string       ");

    start_timer();
    {
        FILE *file=fopen("tonto10.txt","w");
        for(int i=0;i<lCount;i++)
            fputs_unlocked("abcdef\n",file);
        fclose(file);
    }
    end_timer("fputs_unlocked     ");

    start_timer();
    {
        std::ofstream lStream("tonto4.txt");
        for(int i=0;i<lCount;i++)
            lStream << lInteger << ' ';
    }
    end_timer("ostream integer    ");
    
    start_timer();
    {
        io::CTextWriter lWriter(io::file("tonto5.txt"),io::EMode::TRUNCATE);
        for(int i=0;i<lCount;i++)
            lWriter << lInteger << ' ';
    }
    end_timer("CTextWriter integer");

    start_timer();
    {
        boost::iostreams::stream<boost::iostreams::file_sink> lStream("tonto6.txt");
        for(int i=0;i<lCount;i++)
            lStream << lInteger << ' ';
    }
    end_timer("boost integer      ");
    
    start_timer();
    {
        FILE *file=fopen("tonto8.txt","w");
        for(int i=0;i<lCount;i++)
            fprintf(file,"%lu ",lInteger);
        fclose(file);
    }
    end_timer("fprintf integer    ");

    double lSum=0;
    start_timer();
    {
        std::ifstream lStream("tonto4.txt");
        for(int i=0;i<lCount;i++)
        {
            double a;
            lStream >> a;
            lSum+=a;
        }
    }
    end_timer("ifstream double    ");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        io::CTextReader lReader(io::file("tonto5.txt"));
        for(int i=0;i<lCount;i++)
        {
            double a;
            lReader >> a;
            lSum+=a;
        }
    }
    end_timer("CTextReader double ");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        boost::iostreams::stream<boost::iostreams::file_source> lStream("tonto6.txt");
        for(int i=0;i<lCount;i++)
        {
            double a;
            lStream >> a;
            lSum+=a;
        }
    }
    end_timer("boost double       ");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        FILE *file=fopen("tonto8.txt","r");
        for(int i=0;i<lCount;i++)
        {
            double a;
            fscanf(file,"%lf",&a);
            lSum+=a;
        }
        fclose(file);
    }
    end_timer("fscanf double      ");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        std::ifstream lStream("tonto4.txt");
        for(int i=0;i<lCount;i++)
        {
            int a;
            lStream >> a;
            lSum+=a;
        }
    }
    end_timer("ifstream integer   ");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        io::CTextReader lReader(io::file("tonto5.txt"));
        for(int i=0;i<lCount;i++)
        {
            int a;
            lReader >> a;
            lSum+=a;
        }
    }
    end_timer("CTextReader integer");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        boost::iostreams::stream<boost::iostreams::file_source> lStream("tonto6.txt");
        for(int i=0;i<lCount;i++)
        {
            int a;
            lStream >> a;
            lSum+=a;
        }
    }
    end_timer("boost integer      ");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        FILE *file=fopen("tonto8.txt","r");
        for(int i=0;i<lCount;i++)
        {
            int a;
            fscanf(file,"%d",&a);
            lSum+=a;
        }
        fclose(file);
    }
    end_timer("fscanf integer     ");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        std::ifstream lStream("tonto1.txt");
        std::string lString;
        while(std::getline(lStream,lString))
        {
            lSum+=lString.length()+1;
        }
    }
    end_timer("std::getline       ");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        io::PBufferStream lStream=io::open_buffered(io::file("tonto2.txt"),io::EMode::READ);
        std::string lString;
        while(get_line(lStream,lString))
        {
            lSum+=lString.length()+1;
        }
    }
    end_timer("buola::io::get_line");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        boost::iostreams::stream<boost::iostreams::file_source> lStream("tonto3.txt");
        std::string lString;
        while(std::getline(lStream,lString))
        {
            lSum+=lString.length()+1;
        }
    }
    end_timer("boost std::getline ");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        char lString[100];
        FILE *file=fopen("tonto7.txt","r");
        for(int i=0;i<lCount;i++)
        {
            lSum+=strlen(fgets(lString,100,file));
        }
        fclose(file);
    }
    end_timer("fgets              ");
    msg_info() << lSum << "\n";

    lSum=0;
    start_timer();
    {
        char lString[100];
        FILE *file=fopen("tonto10.txt","r");
        for(int i=0;i<lCount;i++)
        {
            lSum+=strlen(fgets_unlocked(lString,100,file));
        }
        fclose(file);
    }
    end_timer("fgets_unlocked     ");
    msg_info() << lSum << "\n";
}